<?php

class DataProvider extends Base
{
    protected $error='';
    protected $model;
    protected $attributes=array();
    protected $params=array();
    protected $sort, $paging, $filter, $elementsCount;
    protected $path=PROVIDERS;
    protected $paginationHtml='';
    protected $data=array();


    public function __construct($model,$params=array())
    {
        if(is_object($model)) $this->model=$model;
        elseif(is_string($model)){
            $model=ucfirst($model);
            $this->model=Model::model($model);
        }else{
            $this->error='Неправильно указана модель в провайдере данных. Это должно быть либо имя модели, либо объект';
        }

        if(is_array($params)){
            if(isset($params['sort']) && $params['sort']){
                if(is_array($params['sort'])) $this->sort=Data::sort($params['sort']);
                elseif(is_object($params['sort'])) $this->sort=$params['sort'];
                else $this->sort=Data::sort();
                unset($params['sort']);
            }
            if(isset($params['paging']) && $params['paging']){
                if(is_array($params['paging'])) $this->paging=Data::paging($params['paging']);
                elseif(is_object($params['paging'])) $this->paging=$params['paging'];
                else $this->paging=Data::paging();
                unset($params['paging']);
            }
            if(isset($params['filter']) && $params['filter']){
                if(is_array($params['filter'])) $this->filter=Data::filter($params['filter']);
                elseif(is_object($params['filter'])) $this->filter=$params['filter'];
                else $this->filter=Data::filter();
                unset($params['filter']);
            }
            if(isset($params['elementsCount']) && $params['elementsCount']){
                if(is_array($params['elementsCount'])) $this->sort=Data::elementsPerPage($params['elementsCount']);
                elseif(is_object($params['elementsCount'])) $this->elementsCount=$params['elementsCount'];
                else $this->elementsCount=Data::elementsPerPage();
                unset($params['elementsCount']);
            }
            if(isset($params['attributes'])){
                $this->attributes=$params['attributes'];
                unset($params['attributes']);
            }
            $this->params=$params;
        }else{
            $this->error.=' Неверно переданы параметры провайдеру данных. Параметры передаются в виде объекта.';
        }

        if($this->error) Sys::app()->error=$this->error;
    }

    public function getModel()
    {
        return $this->model;
    }

    public function getData()
    {
        if(!$attributes=$this->attributes){
            if($this->sort && is_object($this->sort))$attributes=array_merge($attributes,$this->sort->attributes);
            if($this->elementsCount && is_object($this->elementsCount)) $attributes=array_merge($attributes,$this->elementsCount->attributes);
            if($this->paging && is_object($this->paging)){
                $this->paging->model=$this->model;
                $attributes=array_merge($attributes,$this->paging->attributes);
            }
            if($this->filter && is_object($this->filter)){
                $this->filter->model=$this->model;
                $attributes=array_merge($attributes,$this->filter->attributes);
            }
        }

        if($attributes){
            $trueAttributes=$attributes=array_merge(Sys::app()->request->params,$attributes);
            $sort=isset($trueAttributes['sort']) ? $trueAttributes['sort'] : '';

            if(!$this->sort) unset($trueAttributes['sort'],$attributes['sort']);
            if(!$this->paging && !$this->elementsCount) unset($trueAttributes['limit'],$attributes['limit']);
            elseif(!$this->paging && $this->elementsCount){
                $trueAttributes=array_merge($trueAttributes,$this->elementsCount->attributes);
                $trueAttributes=array_filter($trueAttributes);
                $attributes=array_merge($attributes,$this->elementsCount->attributes);
            }

            $html=Widget::html();
            $route=Sys::app()->request->route;

            $attributeNames=$this->model->attributeNames;
            $newAttributes=array();
            if($attributes && isset($attributes['sort'])){
                foreach($attributeNames as $name){
                    $attributes['linkName']=$name;
                    $sortVal=$name;
                    if($name==$sort){
                        if(strpos($name,' desc')) $sortVal=str_replace(' desc','',$name);
                        else $sortVal.=' desc';
                    }

                    $attributes['sort']=$sortVal;
                    $attributes['class']='link sort sort-link';

                    //if($this->ajax) $attributes['onClick']='return Data.dataSort(this,true);';


                    $newAttributes[$name]=array(
                        'name'=>$name,
                        'href'=>$html->link($route,$attributes),
                    );
                }

                unset($attributes);
            }

            if($this->filter && is_object($this->filter)){
                foreach($attributeNames as $name){
                    if(isset($newAttributes[$name])){
                        $newAttributes[$name]=array_merge($newAttributes[$name],array(
                            'filter'=>$this->filter->createFilterField($name,$link=Sys::app()->request->createUrl($route,$trueAttributes),array(
                                'elementId'=>'filter-field-'.$name,
                                'class'=>'data filter',
                            )),
                        ));
                    }
                }
            }
            unset($attributeNames);

            if($newAttributes) $this->model->attributeNames=$newAttributes;

            unset($newAttributes);

            if($this->paging){
                $this->paginationHtml=$this->paging->getPagingLinks($trueAttributes);
            }

            return $this->data=$this->model->findAllByAttributes($trueAttributes);
        }
        return $this->data=$this->model->findAll();
    }

    public function getPagination()
    {
        return $this->paginationHtml;
    }

    public function getElementsPerPage()
    {
        $params=$this->params ? $this->params : Sys::app()->request->params;
        unset($params['limit']);
        if($this->elementsCount) return $this->elementsCount->getElements(array_merge(Sys::app()->request->params,$this->attributes,array('elementsCount'=>$this->model->getCount($params))));
        else return '';
    }

    public function getPath()
    {
        return $this->path;
    }

    public function getError()
    {
        return $this->error;
    }

    public function getAjax()
    {
        return $this->ajax ? true : false;
    }
}